{
  "properties" : { },
  "id" : "01c5b7e4a2514dfc8ab0958c48beeb1d",
  "script" : null,
  "groupId" : "ea55584b076149d0b62e309b156a9202",
  "name" : "menu.html",
  "createTime" : null,
  "updateTime" : 1739461945893,
  "lock" : null,
  "createBy" : null,
  "updateBy" : "管理员",
  "path" : "menu.html"
}
================================
<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>|</title>
    <link rel="stylesheet" href="/plugs/layui/css/layui.css" />
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <style>
      html, body {
        height: 100%
      }
      .layui-table .layui-form-select .layui-input{
        height: 28px
      }
      .ws-docs-icon>div {
        display: inline-block; vertical-align: middle; width: 15.9%; height: 105px; line-height: 25px; padding: 20px 0; margin-right: -1px; margin-bottom: -1px; border: 1px solid #e2e2e2; font-size: 14px; text-align: center; color: #777; cursor: pointer; transition: all .3s; -webkit-transition: all .3s;
      }
    </style>
</head>
<body class="layui-padding-2">
  <table class="layui-hide" id="ID-treeTable"></table>

  <script type="text/html" id="TPL-select-type">
    {{#  var typeList = ["目录","菜单","弹层","跳转"]; }}
    <select name="type" lay-filter="select-type" lay-append-to="body">
      {{#  layui.each(typeList, function(i, v){ }}
      <option value="{{= i }}" {{= i === d.type ? 'selected' : '' }}>{{= v }}</option>
      {{#  }); }}
    </select> 
  </script>
  <script type="text/html" id="TPL-select-status">
    {{#  var statusList = ["停用","启用"]; }}
    <select name="status" lay-filter="select-status" lay-append-to="body">
      {{#  layui.each(statusList, function(i, v){ }}
      <option value="{{= i }}" {{= i === d.status ? 'selected' : '' }} >{{= v }}</option>
      {{#  }); }}
    </select>
  </script>

  <script type="text/html" id="TPL-treeTable-toolbar">
    <div class="layui-btn-container">
      <button class="layui-btn layui-btn-sm" lay-event="addRow">添加</button>
      <button class="layui-btn layui-btn-sm layui-border-orange" style="background-color: white;" lay-event="checkIcon">图标参考</button>
    </div>
  </script>
  <script type="text/html" id="TPL-treeTable-tools">
    <div class="layui-btn-container">
      {{#  if(d.type === 0){ }}
        <a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="addChild">添加</a>
      {{# } }}
      {{#  if(d.type != 0){ }}
        <a class="layui-btn layui-btn-red layui-btn-xs {{= 0 === d.status ? ' layui-btn-disabled' : '' }}" lay-event="removeChild">删除</a>
      {{# } }}
    </div>
  </script>

  <script src="/plugs/layui/layui.js"></script>
  <script type="text/javascript">
    layui.use(function(){
      var treeTable = layui.treeTable;
      var table = layui.table;
      var layer = layui.layer;
      var form = layui.form;
      var $ = layui.jquery;

      var updateObj = function(postData) {
        postData['icon'] = postData['icon'].replaceAll('layui-icon ','');
        
        $.ajax({
          url: '/api/system/menu/add', type: 'POST', contentType: "application/json", data: JSON.stringify(postData), success: function(res){
            layer.closeAll();
            if(res.code === 200){
              layer.msg(res.msg, { icon: 1 });
              treeTable.reload(tableId);
            } else {
              layer.alert(res.msg, { icon: 5});
            }
          }
          ,error: function(res, msg){treeTable.reload(tableId);layer.msg('error');}
        });
      }
      var removeObj = function(tableObj, postData) {
        $.ajax({
          url: '/api/system/menu/remove', type: 'DELETE', data: postData, success: function(res){
            layer.closeAll();
            if(res.code === 200){
              layer.msg(res.msg, { icon: 1 });
              tableObj.del();
            } else {
              layer.alert(res.msg, { icon: 5});
            }
          }
          ,error: function(res, msg){layer.msg('error');}
        });
      }

      var tableId = 'ID-treeTable';

      var inst = treeTable.render({
        elem: '#'+tableId, toolbar: '#TPL-treeTable-toolbar',
        url: '/api/system/menu/tree',
        tree: {
          customName: {
            children: 'children', name: 'menuName', id: 'menuId', pid: 'parentId', icon: 'icon'
          },
          data: { rootPid: 'parentId' }, view: { icon: 'layui-icon layui-icon-addition' }
        },
        height: 'full', response: {statusCode: 200},

        cols: [[
          {type: 'checkbox', fixed: 'left'},
          {field: 'menuName', title: 'menuName', edit: 'text'},
          {field: 'menuId', title: 'menuId', width: 80},
          {field: 'menuCode', title: 'menuCode', edit: 'text'},
          {field: 'path', title: 'path', edit: 'text'},
          {field: 'icon', title: 'icon', edit: 'text'},
          {field: 'sort', title: 'sort', edit: 'text'},
          {field: 'type', title: 'type', width: 110, align: 'center', templet: '#TPL-select-type'},
          {field: 'status', title: 'status', width: 100, templet: '#TPL-select-status'},
          {fixed: "right", title: "操作", align: "center", toolbar: "#TPL-treeTable-tools", width: 130} 
        ]],
        page: false,
        done: function(res, curr, count){
          var options = this;

          // 获取当前行数据 - 自定义方法
          inst.getRowData = function(tableId, elem){
            var index = $(elem).closest('tr').data('index');
            return treeTable.getNodeDataByIndex(tableId, index) || {};
          };

          form.on('select(select-type)', function(obj){
            var postData = inst.getRowData(tableId, obj.elem);

            postData['icon'] = postData['icon'].split(' ')[1];
            postData['type'] = obj.value;

            updateObj(postData);
          });
          form.on('select(select-status)', function(obj){
            var postData = inst.getRowData(tableId, obj.elem);

            postData['icon'] = postData['icon'].split(' ')[1];
            postData['status'] = obj.value;

            updateObj(postData);
          });

          treeTable.expandAll(tableId, true);
        }
      });

      // 表头工具栏工具事件
      treeTable.on('toolbar('+tableId+')', function (obj) {
        if (obj.event === 'addRow'){
          var postData = {
            "compontPath":"","icon":"layui-icon-component","menuCode":"xxx","menuName":"新增菜单","path":"/menu","sort":99,"status":1,"type":1,"parentId": 0
          }
          updateObj(postData);
        }
        if (obj.event === 'checkIcon'){
          layer.open({
            title: false,
            type: 1,
            area: ['650px', '540px'], // 宽高
            content: '<#include "@/page/iconlist">'
          });
        }
        
      });
      // 单元格工具事件
      treeTable.on('tool('+ inst.config.id +')', function (obj) {
        var layEvent = obj.event;
        var trData = obj.data;
        
        if (layEvent === "addChild") {
          var postData = {
            "compontPath":"","icon":"layui-icon-component","menuCode":"xxx","menuName":"新增菜单","path":"/menu","sort":99,"status":1,"type":1,"parentId": trData.menuId
          }
          updateObj(postData);
        } else if (obj.event === 'removeChild'){
          if(0 === trData.status){
            return;
          }
          layer.confirm("真的删除 ["+trData.menuName+"]", {title: false}, function (index) {
            removeObj(obj, {id: trData.menuId});
            layer.close(index);
          });
        }
        
      });
      // 单元格编辑事件
      table.on('edit('+ inst.config.id +')', function(obj){
        var field = obj.field; // 得到字段
        var value = obj.value; // 得到修改后的值

        var postData = obj.data; // 得到所在行所有键值
        // 值的校验
        if(field === 'sort'){
          if(!Number(value) == false){
            postData['sort'] = Number(value)
            updateObj(postData);
          }
        } else if (value.length > 0){
          updateObj(postData);
        }
        // 编辑后续操作，如提交更新请求，以完成真实的数据更新
        
      });


    });
  </script>
</body>